#ifndef _MQTT_MESSAGE_H_
#define _MQTT_MESSAGE_H_

#include "Params.h"
#include "Define.h"

#ifdef __cplusplus
extern "C" {
#endif
#define MAX_USER_PROPERTY           (20)

/**
 * @brief 消息类型
 */
typedef enum {
    recvPublish,                    /**接收publish消息*/
    recvHeartBeatRes,               /**接收的ping response消息*/
    recvSubscribeAck,               /**接收的订阅ack*/
    recvUnSubscribeAck,             /**接收取消订阅的ack*/
    recvPublishAck,                 /**接收发布消息ack*/
    recvConnectAck,                 /**接收connect ack*/
    recvDisconnect,                 /**接收disconnect消息*/
} MessageType;
/**
 * @brief
 */
typedef struct {
    uint16_t    len;                /**值长度*/
    uint8_t*    value;              /**值指针*/
} MQTTValue;
/**
 * @brief mqtt用户属性定义
 */
typedef struct {
    MQTTValue   key;                /**key*/
    MQTTValue   value;              /**value*/
} UserProperty;
/**
 * @brief connectAck报文中 ack属性
 */
typedef struct {
    uint8_t                 maxQos;
    uint16_t                maxTopicAlis;
    uint8_t*                clientId;
    uint32_t                maxPacket;
    uint16_t                serverReceiveMax;
    uint8_t                 wildcardSubAvailable;
    uint8_t                 subIdentifierAvailable;
    uint8_t                 sharedSubAvailable;
    UserProperty*           userProperty[MAX_USER_PROPERTY];
} ConnAckProperty;
/**
 * @brief connect报文属性
 */
typedef struct {

    uint16_t        topicAliasMax;                               /**topic 别名最大数量*/
    uint16_t        clientReceiveMax;                            /**client接收的能力*/
    UserProperty*   userProperty[MAX_USER_PROPERTY];             /**用户属性*/
} ConnectProperty;
/**
 * @brief disconnect 报文属性
 */
typedef struct {
    MQTTValue*       reason;                                    /**断开原因*/
    UserProperty*    userProperty[MAX_USER_PROPERTY];           /**用户属性*/
} DisconnectProperty;
/**
 * @brief subscribe 报文属性
 */
typedef struct {
    UserProperty*   userProperty[MAX_USER_PROPERTY];            /**用户属性*/
} SubProperty;
/**
 * @brief unsubscribe 报文属性
 */
typedef struct {
    UserProperty*   userProperty[MAX_USER_PROPERTY];            /**用户属性*/
} UnSubProperty;
/**
 * @brief publish 报文属性
 */
typedef struct {
    uint32_t            expireInterval;
    uint16_t            topicAlias;
    MQTTValue           responseTopic;
    MQTTValue           correlationData;
    uint32_t            subIdentifier;
    UserProperty*       userProperty[MAX_USER_PROPERTY];
} PubProperty;
/**
 * @brief mqtt 接收数据报文定义
 */
typedef struct {

    MessageType     type;
    /**
     * @brief MQTT报文联合体, 内容根据type进行选择
     */
    union {
        /**
         * @brief publish报文
         */
        struct {
            uint8_t         qos;
            char*           topic;
            uint16_t        topicLen;
            uint8_t*        payload;
            uint32_t        payloadLen;
            PubProperty*    pubProp;        /**publish 报文中的属性. MQTT 5.0 特性*/
        } publish;
        /**
         * @brief subscribe ack报文
         */
        struct {
            int32_t     res;
            uint8_t     maxQos;
            uint16_t    packetId;
        } subscribeAck;
        /**
         * @brief unsubscribe ack报文
         */
        struct {
            uint16_t packetId;
        } unsubscribeAck;

        /**
         * @brief publish ack报文
         */
        struct {
            uint16_t    packetId;
        } publishAck;
        /**
         * @brief connect ack 报文
         */
        struct {
            uint8_t         reasonCode;
            ConnAckProperty property;       /** 建连回复报文中的属性. MQTT 5.0 特性 */
        } connectAck;
        /**
         * @brief disconnect 报文
         */
        struct {
            uint8_t reasonCode;
        } disconnect;
    } data;

} RecvMQTTMessage;

/**
* @brief 定义接收消息处理器定义
* @param handle         MQTT 句柄
* @param packet         接收MQTT消息
* @param context        用户上下文
*/
typedef void (*RecvHandler)(void *handle, const RecvMQTTMessage* packet, void *context);

#ifdef __cplusplus
}
#endif
#endif //_MQTT_MESSAGE_H_
